﻿// This source is subject to Microsoft Public License (Ms-PL).
// Please see http://taskcardcreator.codeplex.com for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Xps.Packaging;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.Windows.Controls.Ribbon;
using WorkItemReportInterface;
using MessageBox = System.Windows.MessageBox;
using Microsoft.Practices.EnterpriseLibrary.Logging;

namespace TaskCardCreator
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : RibbonWindow, System.Windows.Forms.IWin32Window
  {
    private ProjectInfo projInfo;
    private WorkItemStore workItemStoreService;
    private WorkItemTypeCollection wiTypes;

    [ImportMany(typeof(IWorkItemReport))]
    private IEnumerable<IWorkItemReport> reports;

    public MainWindow()
    {
      LoadReports();

      InitializeComponent();
    }

    public IntPtr Handle
    {
      get
      {
        return ((HwndSource)PresentationSource.FromVisual(this)).Handle;
      }
    }

    private void LoadReports()
    {
      Logger.Write("Entering LoadReports method");

      // An aggregate catalog that combines multiple catalogs
      var catalog = new AggregateCatalog();
      // Adds all the parts found in all assemblies in 
      // the same directory as the executing program
      catalog.Catalogs.Add(
       new DirectoryCatalog(
        Path.GetDirectoryName(
         Assembly.GetExecutingAssembly().Location)));

      // Create the CompositionContainer with the parts in the catalog
      var container = new CompositionContainer(catalog);

      // Fill the imports of this object
      container.ComposeParts(this);
    }

    private void selectProjectButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering selectProjectButton_Click method");

      using (TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false))
      {
        DialogResult result = tpp.ShowDialog(this);

        if (result == System.Windows.Forms.DialogResult.OK)
        {
          ReportButton.IsEnabled = true;

          projInfo = tpp.SelectedProjects[0];
          workItemStoreService = tpp.SelectedTeamProjectCollection.GetService<WorkItemStore>();
          foreach (Project project in workItemStoreService.Projects)
          {
            if (project.Name == projInfo.Name)
            {
              wiTypes = project.WorkItemTypes;
              break;
            }
            wiTypes = null;
          }
        }
      }
    }

    private enum ProjectTypes
    {
      MicrosoftVisualStudioScrum10,
      MSFforAgileSoftwareDevelopmentv50,
      UpgradedProcessTemplate,
      Unknown
    }

    /// <summary>
    /// Try to detect process template. This is done by looking at specific work item types
    /// </summary>
    /// <returns>Project type</returns>
    private ProjectTypes ProjectType()
    {
      Logger.Write("Entering ProjectType method");

      if (wiTypes == null)
      {
        Logger.Write("Returning ProjectTypes.Unknown");
        return ProjectTypes.Unknown;
      }

      if (wiTypes.Count == 0)
      {
        Logger.Write("Returning ProjectTypes.Unknown");
        return ProjectTypes.Unknown;
      }

      //An MSF Agile v4.0 process template can be upgraded to MSF Agile v5.0, this is messy and so it is unsupported.
      if (wiTypes.Contains("User Story") == true && wiTypes.Contains("Scenario") == true)
      {
        Logger.Write("Returning ProjectTypes.UpgradedProcessTemplate");
        return ProjectTypes.UpgradedProcessTemplate;
      }

      // Only the Scrum process template has this type
      if (wiTypes.Contains("Product Backlog Item") == true)
      {
        Logger.Write("Returning ProjectTypes.MicrosoftVisualStudioScrum10");
        return ProjectTypes.MicrosoftVisualStudioScrum10;
      }

      // Only the MSF for Agile process template has this type
      if (wiTypes.Contains("User Story") == true)
      {
        Logger.Write("Returning ProjectTypes.MSFforAgileSoftwareDevelopmentv50");
        return ProjectTypes.MSFforAgileSoftwareDevelopmentv50;
      }

      Logger.Write("Returning ProjectTypes.Unknown");
      return ProjectTypes.Unknown;
    }

    private void generateReport_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering generateReport_Click method");

      if (projInfo == null)
        return;

      // Create report
      IWorkItemReport reportTemplate = null;
      IEnumerable<WorkItem> workItems = null;
      switch (ProjectType())
      {
        case ProjectTypes.MicrosoftVisualStudioScrum10:
          var scrumReports = from r in reports
                             where r.ProcessTemplate == ReportType.MicrosoftVisualStudioScrum10
                             select r;
          var scrumPopup = new TaskCardDetailsPopup(scrumReports) { Owner = this };
          scrumPopup.queries.BuildQueryTree(workItemStoreService.Projects[projInfo.Name].QueryHierarchy, projInfo.Name);
          scrumPopup.workItemStoreService = workItemStoreService;
          if (scrumPopup.ShowDialog() == false)
            return;
          reportTemplate = scrumPopup.SelectedReport;
          workItems = scrumPopup.listView.SelectedItems.Cast<WorkItem>().ToList();
          break;
        case ProjectTypes.MSFforAgileSoftwareDevelopmentv50:
          var agileReports = from r in reports
                             where r.ProcessTemplate == ReportType.MSFforAgileSoftwareDevelopmentv50
                             select r;
          var agilePopup = new TaskCardDetailsPopup(agileReports) { Owner = this };
          agilePopup.queries.BuildQueryTree(workItemStoreService.Projects[projInfo.Name].QueryHierarchy, projInfo.Name);
          agilePopup.workItemStoreService = workItemStoreService;
          if (agilePopup.ShowDialog() == false)
            return;
          reportTemplate = agilePopup.SelectedReport;
          workItems = agilePopup.listView.SelectedItems.Cast<WorkItem>().ToList();
          break;
        case ProjectTypes.UpgradedProcessTemplate:
          MessageBox.Show("The current project is using an upgraded process template." + Environment.NewLine +
                          "This process template is not supported." + Environment.NewLine +
                          Environment.NewLine +
                          "Supported process templates:" + Environment.NewLine +
                          "Microsoft Visual Studio Scrum 1.0" + Environment.NewLine +
                          "MSF for Agile Software Development v5.0", "Error");
          return;
        default:
          MessageBox.Show(
            "Supported process templates:" + Environment.NewLine +
            "Microsoft Visual Studio Scrum 1.0" + Environment.NewLine +
            "MSF for Agile Software Development v5.0", "Error");
          return;
      }

      var ms = new MemoryStream();
      var pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
      string pack = string.Format("pack://{0}.xps", Guid.NewGuid());
      PackageStore.AddPackage(new Uri(pack), pkg);
      var compressionOption = CompressionOption.NotCompressed;
      if (XpsCompression.IsChecked.Value)
        compressionOption = CompressionOption.SuperFast;
      var document = new XpsDocument(pkg, compressionOption, pack);
      var report = reportTemplate.Create(workItems);
      var writer = XpsDocument.CreateXpsDocumentWriter(document);
      writer.Write(report.DocumentPaginator);

      // Create tab
      var tab = new TabItem { Header = "Report @ " + DateTime.Now.ToLongTimeString() };
      var doc = new DocumentViewer { Document = document.GetFixedDocumentSequence() };
      doc.FitToMaxPagesAcross(1);
      tab.Content = doc;
      tabControl.Items.Insert(1, tab);
      tabControl.SelectedItem = tab;
    }

    private void GoToWebSiteButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering GoToWebSiteButton_Click method");
      System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(@"http://taskcardcreator.codeplex.com"));
    }

    private void CheckForUpdatesButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering CheckForUpdatesButton_Click method");
      System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(@"http://taskcardcreator.codeplex.com/releases"));
    }

    private void SubmitBugButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering SubmitBugButton_Click method");
      System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(@"http://taskcardcreator.codeplex.com/workitem/list/advanced"));
    }

    private void HelpButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering HelpButton_Click method");
      System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(@"http://taskcardcreator.codeplex.com"));
    }

    private void ExitButton_Click(object sender, RoutedEventArgs e)
    {
      Logger.Write("Entering ExitButton_Click method");
      Close();
    }
  }
}